home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 1 / Cream of the Crop 1.iso / WINDOWS / PROFFT.ARJ / COMPWIN.CPP < prev    next >
C/C++ Source or Header  |  1992-04-29  |  39KB  |  1,196 lines

  1. /****************************************************************************
  2.     COMPWIN.CPP     Denne filen inneholder (i denne rekkef°lgen):
  3. *****************************************************************************
  4. void TComplexWindow::TComplexWindow(PTWindowsObject AParent,
  5.                 LPSTR lpszCaption, HANDLE hComplexPict, BITMAPINFO *bmpInfo,
  6.                 HANDLE hBitmap) : TGenericPicWindow (AParent, lpszCaption,
  7.                                                         bmpInfo, hBitmap)
  8. TComplexWindow::~TComplexWindow()
  9. void TComplexWindow::GetWindowClass(WNDCLASS& wc)
  10. LPSTR TComplexWindow::GetClassName()
  11. void TComplexWindow::WMSetCursor(RTMessage Msg)
  12. void TComplexWindow::CopyComplex(HANDLE hSource, HANDLE hTarget)
  13. BOOL TComplexWindow::ConvertComplexToBMP(HANDLE hTempComplex, HANDLE hNewBitmap)
  14. BOOL TComplexWindow::MakeComplexConjugate(HANDLE hComp)
  15. BOOL TComplexWindow::InvertSignCheckerboard(HANDLE hComp)
  16. void TComplexWindow::PerformIFFT()
  17. void TComplexWindow::PerformFFT()
  18. BOOL TComplexWindow::FFT(HANDLE hTarget)
  19. BOOL TComplexWindow::ConvertBMPToComplex(HANDLE hSourceBitmap, HANDLE hTargetComplex)
  20. BOOL TComplexWindow::UpdateBitmap()
  21. void TComplexWindow::Paint(HDC, PAINTSTRUCT& PaintInfo)
  22. BOOL TComplexWindow::LockComplex()
  23. void TComplexWindow::UnlockComplex()
  24. void TComplexWindow::WMMDIActivate(RTMessage Msg)
  25. void TComplexWindow::SetMenuItems(WORD wStatus)
  26. void TComplexWindow::PrepareToExecuteFilter()
  27. void TComplexWindow::ExecuteFilter(HDC hdcMem)
  28. ****************************************************************************/
  29. #include <owl.h>
  30. #include <stdlib.h>
  31. #include <stdio.h>
  32. #include <filedial.h>
  33. #include <static.h>
  34. #include <dir.h>
  35. #include <dos.h>
  36. #include <string.h>
  37. #include <mem.h>
  38. #include <math.h>
  39.  
  40. #pragma hdrstop
  41. #include "profftid.h" // Symbolske konstanter
  42. #include "profft.h"   // Klassedefinisjoner
  43. #include "prcomp.h"   // Kompleks struktur + komplekse konst.
  44.  
  45. void TComplexWindow::TComplexWindow(PTWindowsObject AParent,
  46.                 LPSTR lpszCaption, HANDLE hComplexPict, BITMAPINFO *bmpInfo,
  47.                 HANDLE hBitmap) : TGenericPicWindow (AParent, lpszCaption,
  48.                                                         bmpInfo, hBitmap, FALSE)
  49. /****************************************************************************
  50. Konstruktoren til TComplexWindow setter opp en del standardverdier og
  51. klargj°r noen ressurser som skal brukes i dette objektet. Noen av
  52. parametrene sendes direkte videre til TGenericPicWindow (superklassen)
  53. sin konstruktor.
  54.  
  55. PTWindowObject AParent     Peker til foreldreobjektet.
  56.  
  57. LPSTR lpszCaption     Peker til vindusoverskriften (vanligvis filnavnet
  58.                                      siden TGenericPicWindow konstruktoren lager riktig
  59.                                      overskrift ut av filnavnet).
  60.  
  61. HANDLE hComplexPict     Handle til σ ta i mot det komplekse bildet.
  62.                                          OBS! Mσ vµre allokert pσ forhσnd.
  63.  
  64. BITMAPINFO *bmpInfo  Peker til en klargj°rt bildestruktur.
  65.  
  66. HANDLE hBitmap    Handle til et bitmap. Mσ vµre allokert pσ forhσnd!
  67.  
  68. Kodet av:   MK
  69. Modifisert:    MK  20.04.92  La til st°tte for filtre (lagde brushen)
  70.                                 21.04.92    Lagret filterfargeverdien til systemet.
  71. *****************************************************************************/
  72. {
  73.     LOGBRUSH logbrush = {BS_SOLID, DB_FILTERCOLOUR, 0};
  74.     HDC hdc;
  75.  
  76.     hComplex = hComplexPict;
  77.     bDirty = FALSE;                    // Bildet trenger forel°pig ingen oppdatering
  78.     bShowFilter = FALSE;        // Ikke vis filterellipser
  79.     bButtonDown = FALSE;
  80.     bRescale = TRUE;                // Trenger forel°pig ingen reskalering
  81.     iFilterType = 0;                // Det er ikke filtrert
  82.  
  83.     //  Lager et komplekst tall = 0 til bruk ved filtrering
  84.     compZero.re = 0.0; compZero.im = 0.0;
  85.  
  86.     //  Husk om bildet (dvs. transformen) var sentrert
  87.     bWasShiftCentered = bShiftCenter;
  88.  
  89.     //  Lag penn og fyllfarge som skal brukes til filtrene og
  90.     //  frihσndstegning.
  91.     hbrRed = CreateBrushIndirect((LOGBRUSH FAR *)&logbrush);
  92.     hpenRed = CreatePen(PS_SOLID, 1, DB_FILTERCOLOUR);
  93.  
  94.     //  Ta vare pσ hvordan fargen r°d blir representert pσ dette system
  95.     //  slik at vi kan kjenne igjen fargen ved frihσndsfiltrering.
  96.     hdc = GetDC(HWindow);
  97.     rgbRed = SetPixel(hdc, 0, 0, DB_FILTERCOLOUR);
  98.     ReleaseDC(HWindow, hdc);
  99. }
  100.  
  101. TComplexWindow::~TComplexWindow()
  102. /****************************************************************************
  103. Fjerner ressursene som dette komplekse bildet har brukt.
  104. Kodet av:   MK
  105. Modifisert:    MK  20.04.92  Deallokerte ogsσ den nye brushen.
  106. *****************************************************************************/
  107. {
  108.     if (hComplex!=NULL)
  109.         GlobalFree(hComplex);
  110.     if (hbrRed!=NULL)
  111.         DeleteObject(hbrRed);
  112.     if (hpenRed!=NULL)
  113.         DeleteObject(hpenRed);
  114. }
  115.  
  116. void TComplexWindow::GetWindowClass(WNDCLASS& wc)
  117. /****************************************************************************
  118. Henter vindusklassen og standardikon for vinduet.
  119.  
  120. Kodet av:   MK 28.04.92
  121. *****************************************************************************/
  122. {
  123.     TGenericPicWindow::GetWindowClass(wc);
  124.     wc.hIcon = LoadIcon(wc.hInstance, "COMPLEX");
  125. }
  126.  
  127. LPSTR TComplexWindow::GetClassName()
  128. /****************************************************************************
  129. Returnerer vindusklassen.
  130.  
  131. Kodet av:   MK 28.04.92
  132. *****************************************************************************/
  133. {
  134.     return "PROfft:ComplexWindow";
  135. }
  136.  
  137.  
  138. void TComplexWindow::WMSetCursor(RTMessage Msg)
  139. /****************************************************************************
  140. Denne velger riktig cursor hvis brukeren peker i et komplekst bilde.
  141. Kursoren skal da vise frihσndsfilteret (en sirkel eller firkant).
  142.  
  143. RTMessage Msg  Sendes videre hvis vi ikke er i vinduet klientomrσde.
  144.  
  145. Kodet av:        MK 25.04.92
  146. *****************************************************************************/
  147. {
  148.     if (Msg.LP.Lo != HTCLIENT)  //  Hvis vi ikke er i klientomrσdet
  149.     {                           //  ikke gj°r noe spesiellt.
  150.         DefWndProc(Msg);
  151.         return;
  152.     }
  153.  
  154.     //  Hvis vi er i klientomrσdet, vis viskelµrcursoren
  155.     SetCursor(((TMainWindow *)Parent)->hcrRubber);
  156. }
  157.  
  158. void TComplexWindow::CopyComplex(HANDLE hSource, HANDLE hTarget)
  159. /****************************************************************************
  160. Kopierer fra et komplekst bilde til et annet. Merk! Bruker dette objektet
  161. sine bildestrukturdata. MERK! Begge handlene mσ vµre ferdig allokerte pσ
  162. forhσnd.
  163.  
  164. HANDLE hSource     Handle til orginalbildet.
  165. HANDLE hTarget     Handle til kopibildet.
  166.  
  167. Kodet av:        MK 02.04.92
  168. *****************************************************************************/
  169. {
  170.     prcomplex huge *source, huge *destination;
  171.     int iY, iMaxY, iSize, n;
  172.  
  173.     source = (prcomplex huge *)GlobalLock(hSource);
  174.     destination = (prcomplex huge *)GlobalLock(hTarget);
  175.  
  176.     //  Sjekk om vi fσr tak peker til bildedataene
  177.     if ((source!=NULL) && (destination!=NULL)) {
  178.         iMaxY = bmpInfo->bmiHeader.biHeight-1;
  179.         n = bmpInfo->bmiHeader.biWidth;
  180.         iSize = n*sizeof(prcomplex);
  181.  
  182.         //  Kopier bildet rad for rad
  183.         for (iY=0;iY<=iMaxY;iY++)
  184.             _fmemcpy(&destination[(long)(iY)*n], &source[(long)(iY)*n], iSize);
  185.     }
  186.     else
  187.         MessageBox(HWindow, "TComplexWindow::CopyComplex lock failed",
  188.                 ERROR_CAPTION, MB_ERROR);
  189.     GlobalUnlock(hSource);
  190.     GlobalUnlock(hTarget);
  191. }
  192.  
  193. BOOL TComplexWindow::ConvertComplexToBMP(HANDLE hTempComplex, HANDLE hNewBitmap)
  194. /****************************************************************************
  195. Denne konverterer et komplekst bilde til et bitmap bilde. Den tar
  196. tak i den reelle delen og fors°ker σ gj°re om den til et heltall fra
  197. 0 til 255 (BYTE). Den kalles etter at brukeren har valgt og utf°rt
  198. IFFT rett f°r programmet skal opprette et nytt TPictureWindow objekt.
  199.  
  200. HANDLE hTempComplex  Handle til det komplekse bildet
  201. HANDLE hNewBitmap         Handle til bitmapbildet som skal motta data.
  202.  
  203. Kodet av:        MK 23.04.92
  204. Modifisert: MK 28.04.92  La inn "usentrering" av lave frekvenser her.
  205. *****************************************************************************/
  206. {
  207.     int iX, iY, iMaxX, iMaxY, iW, iH;
  208.     prcomplex rTemp;
  209.     real r;
  210.     BYTE bPixel;
  211.     BOOL bCancel;
  212.  
  213.     //  Opprett statusvindu
  214.     pdbProgress = new TProgressDialog(this, "PROGRESS", "Finishing IFFT");
  215.     GetApplication()->MakeWindow(pdbProgress);
  216.     SendMessage(((TProgressDialog *)pdbProgress)->HWindow,
  217.             WM_SETPROGRESSTEXT,
  218.             0, (long)((LPSTR) "Converting complex picture to bitmap picture.."));
  219.  
  220.     iH = (int)(bmpInfo->bmiHeader.biHeight);
  221.     iW = (int)(bmpInfo->bmiHeader.biWidth);
  222.     iMaxX = iW-1;
  223.     iMaxY = iH-1;
  224.     r = (real)iW;
  225.  
  226.     //  Husker n^4, fordi vi mσ skalere ned med denne faktoren etter at
  227.     //  bildet er transformert.
  228.     r = r*r*r*r;
  229.  
  230.     for (iY=0;iY<=iMaxY;iY++)
  231.     {
  232.         //  Vis hvor langt vi er kommet
  233.         SendMessage(pdbProgress->HWindow, WM_FIRST + WM_SETPROGRESS,
  234.                 0, (((long)100*(iY))/(iMaxY)));
  235.  
  236.         //  Hvis brukeren avbryter, sσ slutt
  237.         if (bCancel=pdbProgress->CancelPressed())
  238.             break;
  239.  
  240.         for (iX=0;iX<=iMaxX;iX++)
  241.         {
  242.             GetComplex(hTempComplex, iX, iY, iW, iH, &rTemp);
  243.  
  244.             //  Rund av til nµrmeste heltall
  245.             if (rTemp.re-floor(rTemp.re)>=0.5)
  246.                 rTemp.re += 1; // For σ minske evt. avrundingsfeil..
  247.  
  248.             //  Gj°r om til en BYTE som skal inn i bitmap bildet.
  249.             bPixel = (BYTE) (rTemp.re/r);
  250.  
  251.             //  Hvis lave frekvenser var sentrert, gj°r om dette igjen.
  252.             if (bWasShiftCentered)
  253.                 if (((iX+iY) & 1)!=0)
  254.                     bPixel = 255-bPixel;
  255.  
  256.             SetBMPPixel(hNewBitmap, iX, iY, iW, iH, bPixel);
  257.         }
  258.     }
  259.     DestroyWindow(pdbProgress->HWindow);
  260.  
  261.     //  Returnerer om denne funksjonen ble fullf°rt.
  262.     return !bCancel;
  263. }
  264.  
  265. BOOL TComplexWindow::MakeComplexConjugate(HANDLE hComp)
  266. /****************************************************************************
  267. Denne klargj°r et komplekst bilde for σ ta invers transformen. Invers-
  268. transformen bestσr av σ sende det kompleks konjugerte bildet til den
  269. orginale FFT algortimen.
  270.  
  271. HANDLE hComp  Handle til det bildet som skal klargj°res.
  272.  
  273. Kodet av:        MK  23.04.92
  274. *****************************************************************************/
  275. {
  276.     int iX, iY, iMaxX, iMaxY, iW, iH;
  277.     prcomplex compZ1;
  278.     prcomplex huge *hpComp;
  279.     BOOL bCancel;
  280.  
  281.     iW = (int)bmpInfo->bmiHeader.biWidth;
  282.     iMaxX = iW-1;
  283.     iH = (int)bmpInfo->bmiHeader.biHeight;
  284.     iMaxY = iH-1;
  285.  
  286.     //  Vis statusvindu
  287.     pdbProgress = new TProgressDialog(this, "PROGRESS", "Preparing for IFFT");
  288.     GetApplication()->MakeWindow(pdbProgress);
  289.     SendMessage(((TProgressDialog *)pdbProgress)->HWindow,
  290.             WM_SETPROGRESSTEXT,
  291.             0, (long)((LPSTR) "Calculating complex conjugate.."));
  292.  
  293.     for (iY=0;iY<=iMaxY;iY++)
  294.     {
  295.         SendMessage(pdbProgress->HWindow, WM_FIRST + WM_SETPROGRESS,
  296.                 0, (((long)100*(iY))/(iMaxY)));
  297.         if (bCancel=pdbProgress->CancelPressed())
  298.             break;
  299.         for (iX=0;iX<=iMaxX;iX++)
  300.         {
  301.             //  Regn ut den komplekskonjugerte og sett denne tilbake i bildet.
  302.             GetComplex(hComp, iX, iY, iW, iH, &compZ1);
  303.             compZ1.im = -compZ1.im;
  304.             SetComplex(hComp, iX, iY, iW, iH, &compZ1);
  305.         }
  306.     }
  307.     DestroyWindow(pdbProgress->HWindow);
  308.     return !bCancel;
  309. }
  310.  
  311. void TComplexWindow::PerformIFFT()
  312. /****************************************************************************
  313. Klargj°r for inverstransformen. Oppretter et midlertidig komplekst bilde
  314. som fungerer som arbeidsbilde og et vanlig bitmapbilde som skal motta
  315. det inverstransformerte bildet.
  316.  
  317. Kodet av:        MK  23.04.92
  318. *****************************************************************************/
  319. {
  320.     HANDLE hTempComplex, hNewBitmap;
  321.     BITMAPINFO *bmpNewInfo;
  322.     PTWindowsObject ptTemp;
  323.     BOOL bOK;
  324.  
  325.     GlobalCompact(-1);  //  Rydd opp f°r vi fors°ker σ allokere minne
  326.  
  327.     //  Fors°ker σ allokere plass til et midlertidig arbeidsbilde
  328.     hTempComplex = GlobalAlloc(GMEM_PROFFTDATA,
  329.             bmpInfo->bmiHeader.biWidth*bmpInfo->bmiHeader.biHeight
  330.             *sizeof(prcomplex)+MS_BUG);
  331.  
  332.     //  Allokerer plass til bitmapbildet som skal motta inverstransformen.
  333.     hNewBitmap = GlobalAlloc(GMEM_PROFFTDATA,
  334.             bmpInfo->bmiHeader.biSizeImage+MS_BUG);
  335.     if ((hTempComplex != NULL) && (hNewBitmap!=NULL))
  336.     {
  337.         //  Oppretter en midlertidig arbeidskopi av det komplekse bildet
  338.         CopyComplex(hComplex, hTempComplex);
  339.  
  340.         //  Hvis brukeren ikke avbryter klargj°ringen..
  341.         if (bOK=MakeComplexConjugate(hTempComplex))
  342.         {
  343.             //  Utf°r inverstransformen (dvs. transformen med kompleks
  344.             //  konjugerte inndata).
  345.             if (bOK=FFT(hTempComplex))
  346.             {
  347.                 //  Hvis brukeren ikke avbr°t sσ konverter til et BMP bilde
  348.                 bOK = ConvertComplexToBMP(hTempComplex, hNewBitmap);
  349.             }
  350.         }
  351.         GlobalFree(hTempComplex);     // Frigj°r det midlertidige arbeidsbildet (komplekst)
  352.  
  353.         // Lager en kopi av bildestrukturdataene
  354.         if (bOK)
  355.         {
  356.             //  Hvis brukeren ikke avbr°t..
  357.             bmpNewInfo = MakeDuplicateBMPInfo(bmpInfo);
  358.  
  359.             // Opprett et nytt bitmap barnevindu (TPictureWindow) objekt
  360.             ((TMainWindow *)Parent)->CreateChild(FileName, bmpNewInfo, hNewBitmap);
  361.         }
  362.     }
  363.     else
  364.     {
  365.         MessageBox(HWindow, "IFFT: Not enough memory for new complex/bitmap picture", ERROR_CAPTION, MB_ERROR);
  366.         bOK = FALSE;
  367.     }
  368.     if (!bOK)
  369.     {
  370.         //  Deallokerer minne hvis funksjonen ikke ble fullf°rt.
  371.         GlobalFree(hTempComplex);
  372.         GlobalFree(hNewBitmap);
  373.     }
  374. }
  375.  
  376. void TComplexWindow::PerformFFT()
  377. /****************************************************************************
  378. Klargj°r for fouriertransformen. Konverterer bitmap bildet til et komplekst
  379. bilde som det sσ utf°res fouriertransformen pσ.
  380.  
  381. Kodet av:        MK  23.04.92
  382. *****************************************************************************/
  383. {
  384.     if (ConvertBMPToComplex(hBitmap, hComplex))
  385.     {
  386.         //  Hvis brukeren ikke avbr°t konvertering, utf°r FFT
  387.         if (FFT(hComplex))
  388.         {
  389.             // Ber det komplekse bilde regne og vise sin amp. representasjon
  390.             bDirty = TRUE;
  391.             InvalidateRect(HWindow, NULL, FALSE);
  392.         }
  393.         else
  394.             CloseWindow();
  395.     }
  396.     else
  397.         CloseWindow();
  398. }
  399.  
  400. BOOL TComplexWindow::FFT(HANDLE hTarget)
  401. /****************************************************************************
  402. Utf°rer fouriertransformen. Denne rutinen kan ogsσ brukes til invers-
  403. transformen ved at man fikser litt pσ inndataene (se PerformIFFT()).
  404. MERK! Bruker dette objektet sine bildestrukturdata.
  405.  
  406. HANDLE hTarget    Handle til det komplekse bildet som FFT skal utf°res pσ.
  407.  
  408. Kodet av:        MK  03.04.92
  409. Oppdatert:    MK  23.04.92  Klargjort for inverstransformen ved at den
  410.                                                     tar et komplekst bilde som parameter.
  411. *****************************************************************************/
  412. {
  413.     int n, iX, iY, iW, iH, iTest;
  414.     prcomplex *z1, *z2, *ptfft, compZ;
  415.     int iSize, iRet, iPixel, iMaxY, iMaxX;
  416.     char acMessage[40];
  417.     prcomplex huge *hpComplexPict;
  418.     BOOL bCancel;
  419.  
  420.     bCancel = FALSE;
  421.     hpComplexPict = (prcomplex huge *)GlobalLock(hTarget);
  422.     if (hpComplexPict!=NULL)
  423.     {
  424.         iH = (int)(bmpInfo->bmiHeader.biHeight);
  425.         iMaxY = iH-1;
  426.         iW = (int)(bmpInfo->bmiHeader.biWidth);
  427.         iMaxX = iW - 1;
  428.         n = iW;
  429.         iSize = sizeof(prcomplex)*n;
  430.  
  431.     // Klargj°r statusvindu
  432.         pdbProgress = new TProgressDialog(this, "PROGRESS", "FFT/IFFT progress"); //M
  433.         GetApplication()->MakeWindow(pdbProgress);
  434.  
  435.         // Allokerer arbeidsbuffere til FFT
  436.         z1 = (prcomplex*) malloc(iSize);
  437.         if (z1!=NULL)
  438.         {
  439.             z2 = (prcomplex*) malloc(iSize);
  440.             if (z2!=NULL)
  441.             {
  442.                 SendMessage(pdbProgress->HWindow,
  443.                         WM_FIRST + WM_SETPROGRESSTEXT,
  444.                         0, (long)((LPSTR) "Transforming rows.."));
  445.  
  446.                 // Transformerer radvis
  447.                 for (iY=0;iY<=iMaxY;iY++)
  448.                 {
  449.                     SendMessage(pdbProgress->HWindow, WM_FIRST + WM_SETPROGRESS,
  450.                             0, (((long)100*(iY))/(2*iMaxY)));
  451.                     if (bCancel=pdbProgress->CancelPressed())
  452.                         break;
  453.  
  454.                     //  Kopier fra bildet inn i arbeidsomrσdet
  455.                     _fmemcpy(z1, &hpComplexPict[((long)(iY))*n], iSize);
  456.  
  457.                     //  Kj°r den diskrete 1D transformen
  458.                     iRet = fft(z1, z2, n);
  459.                     if (iRet==0)
  460.                     {
  461.                         MessageBox(HWindow, "FFT: Transform failed. Out of memory",
  462.                                 ERROR_CAPTION, MB_ERROR);
  463.                         bCancel = TRUE;
  464.                         break;
  465.                     }
  466.                     else
  467.                     {
  468.                         if (iRet==1)
  469.                             ptfft = z1;
  470.                         else
  471.                             ptfft = z2;
  472.  
  473.                         // Multipliserer hver rekke med n if°lge algoritmen for 2D-FFT
  474.                         for (iX=0;iX<=iMaxX;iX++)
  475.                         {
  476.                             ptfft[iX].re *= (real)n;
  477.                             ptfft[iX].im *= (real)n;
  478.                         }
  479.  
  480.                         // Kopiererer den transformerte rekka tilbake i det komplekse bildet
  481.                         _fmemcpy(&hpComplexPict[((long)(iY))*n], ptfft, iSize);
  482.                     }
  483.                 }
  484.                 if (!bCancel)
  485.                 {
  486.                     SendMessage(pdbProgress->HWindow,
  487.                             WM_FIRST + WM_SETPROGRESSTEXT,
  488.                             0, (long)((LPSTR) "Transforming columns.."));
  489.  
  490.                     // Transformerer kolonnevis
  491.                     for (iX=0;iX<=iMaxX;iX++)
  492.                     {
  493.                         SendMessage(pdbProgress->HWindow, WM_FIRST + WM_SETPROGRESS,
  494.                                 0, 50+(((long)100*(iX))/(2*iMaxX)));
  495.                         if (bCancel=pdbProgress->CancelPressed())
  496.                             break;
  497.                         for (iY=0;iY<=iMaxY;iY++)
  498.                         {
  499.                             GetComplex(hTarget, iX, iY, iW, iH, &z1[iY]);
  500.                         }
  501.  
  502.                         //  Kj°r den diskrete 1D transformen
  503.                         iRet = fft(z1, z2, n);
  504.                         if (iRet==0)
  505.                         {
  506.                             MessageBox(HWindow, "FFT: Transform failed. Out of memory",
  507.                                     ERROR_CAPTION, MB_ERROR);
  508.                             bCancel = TRUE;
  509.                             break;
  510.                         }
  511.                         else
  512.                         {
  513.                             if (iRet==1)
  514.                                 ptfft = z1;
  515.                             else
  516.                                 ptfft = z2;
  517.  
  518.                             //  Kopierer tilbake fra arbeidsomrσdet
  519.                             for (iY=0;iY<=iMaxY;iY++)
  520.                             {
  521.                                 SetComplex(hTarget, iX, iY, iW, iH, &ptfft[iY]);
  522.                             }
  523.                         }
  524.                     }
  525.                 }
  526.             }
  527.             else
  528.             {
  529.                 MessageBox(HWindow, "FFT: Out of memory",
  530.                         ERROR_CAPTION, MB_ERROR);
  531.                 bCancel = TRUE;
  532.             }
  533.             free(z2);
  534.         }
  535.         else
  536.         {
  537.             MessageBox(HWindow, "FFT: Out of memory",
  538.                     ERROR_CAPTION, MB_ERROR);
  539.             bCancel = TRUE;
  540.         }
  541.         free(z1);
  542.         GlobalUnlock(hTarget);
  543.         DestroyWindow(pdbProgress->HWindow);
  544.     }
  545.     else
  546.         MessageBox(HWindow, "TComplexWindow::TComplexWindow lock failed",
  547.                 ERROR_CAPTION, MB_ERROR);
  548.     return !bCancel;
  549. }
  550.  
  551. BOOL TComplexWindow::ConvertBMPToComplex(HANDLE hSourceBitmap, HANDLE hTargetComplex)
  552. /****************************************************************************
  553. Konverterer fra et BMP bilde til et komplekst bildet. Merk! Denne algoritmen
  554. er skrevet med tanke pσ hastighet, ikke lesbarhet. Bruker tabelloppslag i
  555. steden for utregning fra BYTE til komplekse tall. MERK! Begge bildene mσ
  556. vµre allokert pσ forhσnd!
  557.  
  558. HANDLE hSourceBitmap   Handle til Bitmapbildet som skal konverteres
  559.  
  560. HANDLE hTargetComplex  Komplekst bilde som mottar konverteringen.
  561.  
  562. Kodet av:        MK  01.04.92
  563. Oppdatert:    MK  04.04.92  Bygget om for tabelloppslag.
  564. *****************************************************************************/
  565. {
  566.     int iX, iY, iPixel, iMaxX, iMaxY, iW, iH;
  567.     prcomplex compZ, far *prByteToComplex;
  568.     TProgressDialog *pdbProgress;
  569.     LPSTR lpBitmap, lpComplex;
  570.     BYTE b;
  571.     BOOL bCancel;
  572.  
  573.     lpBitmap = GlobalLock(hSourceBitmap);
  574.     lpComplex = GlobalLock(hTargetComplex);
  575.     if ((lpBitmap!=NULL) && (lpComplex!=NULL))
  576.     {
  577.         iW = (int)(bmpInfo->bmiHeader.biWidth);
  578.         iMaxX = iW - 1;
  579.         iH = (int)(bmpInfo->bmiHeader.biHeight);
  580.         iMaxY = iH - 1;
  581.         pdbProgress = new TProgressDialog(this, "PROGRESS", "Converting bitmap to complex");
  582.         GetApplication()->MakeWindow(pdbProgress);
  583.         SendMessage(((TProgressDialog *)pdbProgress)->HWindow,
  584.                 WM_SETPROGRESSTEXT,
  585.                 0, (long)((LPSTR) "Creating complex picture.."));
  586.         prByteToComplex = (prcomplex far *)GlobalLock(hByteToComplexTable);
  587.         if (prByteToComplex!=NULL)
  588.         {
  589.             for (iY=0;iY<=iMaxY;iY++)
  590.             {
  591.                 SendMessage(pdbProgress->HWindow, WM_SETPROGRESS,
  592.                         0, (((long)100*(iY))/(iMaxY)));
  593.                 if (bCancel=pdbProgress->CancelPressed())
  594.                     break;
  595.                 for (iX=0;iX<=iMaxX;iX++)
  596.                 {
  597.                     iPixel = (int)GetBMPPixel(hSourceBitmap, iX, iY, iW, iH);
  598.  
  599.                     //  Tabelloppslag for rask konvertering
  600.                     compZ = prByteToComplex[iPixel];
  601.                     if (bWasShiftCentered)
  602.                         if (((iX+iY) & 1)!=0)
  603.                             compZ.re = -compZ.re;
  604.                     SetComplex(hTargetComplex, iX, iY, iW, iH, &compZ);
  605.                 }
  606.             }
  607.             GlobalUnlock(hByteToComplexTable);
  608.         }
  609.         else
  610.             MessageBox(GetActiveWindow(), "ConvertBMPToComplex prByteToComplex==NULL",
  611.                     ERROR_CAPTION, MB_ERROR);
  612.         GlobalUnlock(hSourceBitmap);
  613.         GlobalUnlock(hTargetComplex);
  614.         DestroyWindow(pdbProgress->HWindow);
  615.     }
  616.     else
  617.         MessageBox(GetActiveWindow(), "ConvertBMPToComplex locks failed",
  618.                 ERROR_CAPTION, MB_ERROR);
  619.     return !bCancel;
  620. }
  621.  
  622. BOOL TComplexWindow::UpdateBitmap()
  623. /****************************************************************************
  624. Denne rutinen kalles fra TComplexWindow::Paint og tar seg av reskalering
  625. (hvis n°dvendig) av amplitudeverdiene og tegner bitmaprepresentasjonen inn
  626. i bitmap bildet. Merk! Delen som regner ut maks/min amplitude er skrevet
  627. for hastighet ikke for lettlesbarhet (leser parvis, sammenligner minste
  628. mot minste verdi, st°rste mot st°rste verdi => 3/2*n algoritme).
  629.  
  630. Kodet av:        MK  03.04.92
  631. *****************************************************************************/
  632. {
  633.     int iX, iY, iMaxY, iMaxX, iW, iH;
  634.     long lValue;
  635.     prcomplex compZ1, compZ2;
  636.     BYTE bPixel;
  637.     real rLogAmplitude1, rLogAmplitude2;
  638.     real rScale;
  639.     char acMessage[40];
  640.     BOOL bCancel;
  641.  
  642.     if (LockBMP())
  643.     {
  644.         if (LockComplex())
  645.         {
  646.             bCancel = FALSE;
  647.             pdbProgress = new TProgressDialog(this, "PROGRESS", "Updating amplitude representation");
  648.             GetApplication()->MakeWindow(pdbProgress);
  649.             iH = (int)(bmpInfo->bmiHeader.biHeight);
  650.             iW = (int)(bmpInfo->bmiHeader.biWidth);
  651.             iMaxX = iW - 1;
  652.             iMaxY = iH - 1;
  653.  
  654.             //  Hvis det trengs reskalering. Merk! Ved bruk av filtre settes
  655.             //  ikke denne til TRUE, fordi bitmaprepresentasjonen bruker minste
  656.             //  amplitude = svart. Da blir det et stor mellomrom mellom 0
  657.             //  og den minste verdien, som ville spist verdifull informasjon i
  658.             //  bildet hvis vi hadde foretatt reskalering.
  659.             if (bRescale)
  660.             {
  661.                 SendMessage(pdbProgress->HWindow,
  662.                         WM_SETPROGRESSTEXT,
  663.                         0, (long)((LPSTR) "Rescaling amplitude grayscales.."));
  664.                 MaxLogAmplitude = MINREAL;
  665.                 MinLogAmplitude = MAXREAL;
  666.                 for (iY=0;iY<=iMaxY;iY++)
  667.                 {
  668.                     SendMessage(pdbProgress->HWindow, WM_SETPROGRESS,
  669.                             0, (((long)100*(iY))/(2*iMaxY)));
  670.                     if (bCancel=pdbProgress->CancelPressed())
  671.                         break;
  672.                     iX = 0;
  673.                     while (iX<=iMaxX)
  674.                     {
  675.                         GetComplex(hComplex, iX++, iY, iW, iH, &compZ1);
  676.                         GetComplex(hComplex, iX++, iY, iW, iH, &compZ2);
  677.                         rLogAmplitude1 = FFTLOG(1+sqrt(compZ1.re*compZ1.re+compZ1.im*compZ1.im));
  678.                         rLogAmplitude2 = FFTLOG(1+sqrt(compZ2.re*compZ2.re+compZ2.im*compZ2.im));
  679.                         if (rLogAmplitude1<=rLogAmplitude2)
  680.                         {
  681.                             if (rLogAmplitude1<MinLogAmplitude)
  682.                                 MinLogAmplitude = rLogAmplitude1;
  683.                             if (rLogAmplitude2>MaxLogAmplitude)
  684.                                 MaxLogAmplitude = rLogAmplitude2;
  685.                         }
  686.                         else
  687.                         {
  688.                             if (rLogAmplitude2<MinLogAmplitude)
  689.                                 MinLogAmplitude = rLogAmplitude2;
  690.                             if (rLogAmplitude1>MaxLogAmplitude)
  691.                                 MaxLogAmplitude = rLogAmplitude1;
  692.                         }
  693.                     }
  694.                 }
  695.             }
  696.             if (!bCancel)
  697.             {
  698.                 SendMessage(pdbProgress->HWindow,
  699.                         WM_FIRST + WM_SETPROGRESSTEXT,
  700.                         0, (long)((LPSTR) "Plotting new grayscales.."));
  701.                 rScale = MaxLogAmplitude - MinLogAmplitude;
  702.                 rScale = 255/rScale;
  703.                 for (iY=0;iY<=iMaxY;iY++)
  704.                 {
  705.                     //  Tar hensyn til om reskalering er foretatt nσr
  706.                     //  den viser % av jobben som er ferdig.
  707.                     if (!bRescale)
  708.                         lValue = ((long)100*iY)/iMaxY;
  709.                     else
  710.                         lValue = 50+(((long)100*(iY))/(2*iMaxY));
  711.                     SendMessage(pdbProgress->HWindow, WM_SETPROGRESS, 0, lValue);
  712.                     if (bCancel=pdbProgress->CancelPressed())
  713.                         break;
  714.  
  715.                     //  Konverterer og skalerer
  716.                     for (iX=0;iX<bmpInfo->bmiHeader.biWidth;iX++)
  717.                     {
  718.                         GetComplex(hComplex, iX, iY, iW, iH, &compZ1);
  719.                         rLogAmplitude1 = FFTLOG(1+sqrt(compZ1.re*compZ1.re+compZ1.im*compZ1.im));
  720.                         bPixel = (BYTE)(rScale*(rLogAmplitude1-MinLogAmplitude));
  721.                         SetBMPPixel(hBitmap, iX, iY, iW, iH, bPixel);
  722.                     }
  723.                 }
  724.             }
  725.             UnlockComplex();
  726.             bDirty = FALSE;
  727.             DestroyWindow(pdbProgress->HWindow);
  728.         }
  729.         else
  730.             MessageBox(HWindow, "TComplexWindow::UpdateBitmap LockComplex failed",
  731.                 ERROR_CAPTION, MB_OK);
  732.         UnlockBMP();
  733.     }
  734.     else
  735.         MessageBox(HWindow, "TComplexWindow::UpdateBitmap LockBitmap failed",
  736.             ERROR_CAPTION, MB_OK);
  737.     return !bCancel;
  738. }
  739.  
  740. void TComplexWindow::Paint(HDC, PAINTSTRUCT& PaintInfo)
  741. /****************************************************************************
  742. Viser det komplekse vinduet sin logaritmiske amplituderepresentasjon.
  743. Tar ogsσ og tegner de aktuelle filtrene hvis brukeren holder pσ σ velge
  744. filterradius.
  745.  
  746. PAINTSTRUCT& PaintInfo    Omrσde som trenger σ tegnes.
  747.  
  748. Kodet av:        MK  01.04.92
  749. Oppdatert:    MK    23.04.92  Support for filtre.
  750. *****************************************************************************/
  751. {
  752.     HDC MemoryDC;
  753.     HANDLE OldBitmapHandle;
  754.     RECT ClientRect;
  755.     HRGN hrgn[4];
  756.     int i, iMiddle, iW, iLow, iUp;
  757.     int x11, y11, x12, y12, x21, y21, x22, y22;
  758.  
  759.     if (hBitmap)
  760.     {
  761.         //  Velg riktig palette.
  762.         SelectPalette(PaintInfo.hdc, ((TMainWindow *)Parent)->hPal, 0);
  763.  
  764.         SetMapMode(PaintInfo.hdc, MM_TEXT);
  765.  
  766.         //  Hvis bitmap bildet er forandret mσ vi oppdatere vindusrepr.
  767.         if (bDirty)
  768.             if (!UpdateBitmap())
  769.                 //  Hvis brukeren velger avbryt sσ lukk vinduet.
  770.                 PostMessage(HWindow, WM_CLOSE, 0, 0);
  771.         if (LockBMP())
  772.         {
  773.             //  Tegn ut DeviceIndependent bitmappen pσ bildeflaten
  774.             SetDIBitsToDevice(PaintInfo.hdc, 0, 0,
  775.                 bmpInfo->bmiHeader.biWidth, bmpInfo->bmiHeader.biHeight,
  776.                 0, 0, 0, bmpInfo->bmiHeader.biHeight,
  777.                 &hpBitmap[0], bmpInfo, DIB_RGB_COLORS);
  778.  
  779.             //  Hvis filtrene skal vises (nσr vi er inne og velger radius
  780.             //  i de forskjellige filtrene) sσ vis disse.
  781.             if (bShowFilter)
  782.             {
  783.                 for(i=0;i<4;i++)
  784.                     hrgn[i]=NULL;
  785.  
  786.                 //  Regner ut "boksen" som den innerste sirkelen skal tegnes i
  787.                 iW = (int)(bmpInfo->bmiHeader.biWidth);
  788.                 iLow = iLowerValue+1;
  789.                 iUp = iUpperValue+1;
  790.                 iMiddle = iW / 2;
  791.                 x11 = iMiddle - iLow;
  792.                 y11 = iMiddle - iLow;
  793.                 x12 = iW - (iMiddle - iLow);
  794.                 y12 = iW - (iMiddle - iLow);
  795.                 x11++; y11++;
  796.  
  797.                 //  Hvis vi har et filter med to radiuser, regn ut den andre boksen
  798.                 //  i tillegg
  799.                 if ((iFilterType==CM_FILTERBANDPASS) || (iFilterType==CM_FILTERBANDSTOP))
  800.                 {
  801.                     x21 = iMiddle - iUp;
  802.                     y21 = iMiddle - iUp;
  803.                     x22 = iW - (iMiddle - iUp);
  804.                     y22 = iW - (iMiddle - iUp);
  805.                     x21++;y21++;
  806.                 }
  807.  
  808.                 //  Ut i fra de forskjellige filtertypene velger vi hva som skal
  809.                 //  tegnes i r°dt.
  810.  
  811.                 switch (iFilterType)
  812.                 {
  813.                     case CM_FILTERHIGHPASS:
  814.                     case CM_FILTERBWHIGHPASS:
  815.                         hrgn[2] = CreateEllipticRgn(x11, y11, x12, y12);
  816.                         break;
  817.                     case CM_FILTERLOWPASS:
  818.                     case CM_FILTERBWLOWPASS:
  819.                         hrgn[0] = CreateEllipticRgn(x11, y11, x12, y12);
  820.                         hrgn[1] = CreateRectRgn(0, 0, iW, iW);
  821.                         hrgn[2] = CreateRectRgn(0, 0, iW, iW);
  822.                         CombineRgn(hrgn[2], hrgn[0], hrgn[1], RGN_XOR);
  823.                         DeleteObject(hrgn[0]);
  824.                         DeleteObject(hrgn[1]);
  825.                         break;
  826.                     case CM_FILTERBANDSTOP:
  827.                         hrgn[0] = CreateEllipticRgn(x21, y21, x22, y22);
  828.                         hrgn[1] = CreateEllipticRgn(x11, y11, x12, y12);
  829.                         hrgn[2] = CreateRectRgn(0, 0, iW, iW);
  830.                         CombineRgn(hrgn[2], hrgn[0], hrgn[1], RGN_XOR);
  831.                         DeleteObject(hrgn[0]);
  832.                         DeleteObject(hrgn[1]);
  833.                         break;
  834.                     case CM_FILTERBANDPASS:
  835.                         hrgn[0] = CreateEllipticRgn(x21, y21, x22, y22);
  836.                         hrgn[1] = CreateEllipticRgn(x11, y11, x12, y12);
  837.                         hrgn[3] = CreateRectRgn(0, 0, iW, iW);
  838.                         CombineRgn(hrgn[3], hrgn[0], hrgn[1], RGN_XOR);
  839.                         DeleteObject(hrgn[0]);
  840.                         DeleteObject(hrgn[1]);
  841.                         hrgn[0] = CreateRectRgn(0, 0, iW, iW);
  842.                         hrgn[2] = CreateRectRgn(0, 0, iW, iW);
  843.                         CombineRgn(hrgn[2], hrgn[0], hrgn[3], RGN_XOR);
  844.                         DeleteObject(hrgn[0]);
  845.                         DeleteObject(hrgn[3]);
  846.                         break;
  847.                 }
  848.                 hrgn[0]=CreateRectRgn(0, 0, iW, iW);
  849.                 hrgn[3]=CreateRectRgn(0, 0, iW, iW);
  850.                 CombineRgn(hrgn[3], hrgn[0], hrgn[2], RGN_AND);
  851.  
  852.                 //  Tegn det endelige omrσdet i r°dt.
  853.                 FillRgn(PaintInfo.hdc, hrgn[3], hbrRed);
  854.  
  855.                 //  Fjern de allokerte regionene, de er bare midlertidige
  856.                 for(i=0;i<4;i++)
  857.                     if (hrgn[i]!=NULL)
  858.                         DeleteObject(hrgn[i]);
  859.             }
  860.             ValidateRect(HWindow, NULL);
  861.             UnlockBMP();
  862.         }
  863.         else
  864.             MessageBox(HWindow, "TComplexWindow::Paint LockBitmap failed", ERROR_CAPTION, MB_ERROR);
  865.     }
  866. }
  867.  
  868. BOOL TComplexWindow::LockComplex()
  869. /****************************************************************************
  870. Locker det komplekse bildet og lagrer en huge pointer til det.
  871.  
  872. Returnerer:        TRUE hvis det lot seg lock
  873.                             FALSE ellers
  874.  
  875. Kodet av:     MK
  876. *****************************************************************************/
  877. {
  878.     hpComplex = (prcomplex huge *)GlobalLock(hComplex);
  879.     if (hpComplex!=NULL)
  880.         return TRUE;
  881.     else
  882.         return FALSE;
  883. }
  884.  
  885. void TComplexWindow::UnlockComplex()
  886. /****************************************************************************
  887. Unlocker det komplekse bildet (hpComplex ikke lenger brukbar).
  888.  
  889. Kodet av:     MK    19.04.92
  890. *****************************************************************************/
  891. {
  892.     GlobalUnlock(hComplex);
  893. }
  894.  
  895. void TComplexWindow::WMMDIActivate(RTMessage Msg)
  896. /****************************************************************************
  897. Denne kalles nσr bildet aktiveres. S°rger for σ sette de menyvalgene
  898. som er aktuelle for dette bildet (dvs. enabler FFT, filtre o.l.).
  899.  
  900. RTMessage Msg        Sendes videre til superklassen.
  901.  
  902. Kodet av:   MK
  903. *****************************************************************************/
  904. {
  905.     TGenericPicWindow::WMMDIActivate(Msg);
  906.     if (Msg.WParam)
  907.     {
  908.         SetMenuItems(MF_ENABLED);
  909.     }
  910.     else
  911.         SetMenuItems(MF_GRAYED);
  912. }
  913.  
  914. void TComplexWindow::SetMenuItems(WORD wStatus)
  915. /****************************************************************************
  916. Setter de aktuelle valgene for dette objektet.
  917.  
  918. WORD wStatus        Inneholder hva valgene skal settes til (MF_ENABLED/MF_GRAYED)
  919.  
  920. Kodet av:   MK
  921. *****************************************************************************/
  922. {
  923.     HMENU hMenu;
  924.     int i;
  925.  
  926.     hMenu=GetMenu(((TMainWindow *)Parent)->HWindow);
  927.     if (bWasShiftCentered)
  928.         for (i=CM_FILTERLOWPASS;i<CM_FILTERFREEHAND;i++)
  929.             EnableMenuItem(hMenu, i, wStatus);
  930.     EnableMenuItem(hMenu, CM_FILTERFREEHAND, wStatus);
  931.     EnableMenuItem(hMenu, CM_TRANSIFFT, wStatus);
  932.     EnableMenuItem(hMenu, CM_EDITCOPY, wStatus);
  933.     EnableMenuItem(hMenu, CM_EDITCUT, wStatus);
  934.     EnableMenuItem(hMenu, CM_FILESAVEAS, wStatus);
  935. }
  936.  
  937. void TComplexWindow::PrepareToExecuteFilter()
  938. /****************************************************************************
  939. Klargj°r filterfunksjonen ved σ opprette en kopi av det aktive
  940. TComplexWindow og be dette filtrere seg selv ut i fra de parametre
  941. brukeren har valgt. Denne blir kallt uansett filtertype (ogsσ frihσnds-
  942. filteret).
  943.  
  944. Kodet av:   MK    22.04.92
  945. *****************************************************************************/
  946. {
  947.     int iW, iH;
  948.     HANDLE hNewComplex;
  949.     HANDLE hNewBitmap;
  950.     BITMAPINFO *bmpNewInfo;
  951.     TComplexWindow *ptNewComp;
  952.     HBITMAP hTempBitmap;
  953.     HDC hdc, hdcMem;
  954.  
  955.     GlobalCompact(-1);  //  Rydd opp f°r en fors°ker σ allokere minne
  956.  
  957.     // Alloker minne til et nytt komplekst bilde.
  958.     hNewComplex = GlobalAlloc(GMEM_PROFFTDATA,
  959.             bmpInfo->bmiHeader.biWidth*bmpInfo->bmiHeader.biHeight
  960.             *sizeof(prcomplex)+MS_BUG);
  961.     if (hNewComplex!=NULL)
  962.     {
  963.         // Kopier dataene i det komplekse bildet over i det nye.
  964.         CopyComplex(hComplex, hNewComplex);
  965.  
  966.         // Lag en kopi av bildestrukturdataene
  967.         bmpNewInfo = MakeDuplicateBMPInfo(bmpInfo);
  968.  
  969.         if (bmpNewInfo!=NULL)
  970.         {
  971.             // Alloker minne til et nytt bitmapbilde
  972.             hNewBitmap = GlobalAlloc(GMEM_PROFFTDATA,
  973.                     bmpNewInfo->bmiHeader.biSizeImage+MS_BUG);
  974.             if (hNewBitmap!=NULL)
  975.             {
  976.                 // Kopier bitmap dataene over i det nye bildet
  977.                 CopyBMP(hBitmap, hNewBitmap);
  978.                 iW = (int)bmpInfo->bmiHeader.biWidth;
  979.                 iH = (int)bmpInfo->bmiHeader.biHeight;
  980.  
  981.                 //  Vis filterparametrene (dvs. sirklene som viser radius)
  982.                 bShowFilter = TRUE;
  983.                 UpdateWindow(HWindow);
  984.  
  985.                 //  Opprett en tegneflate som inneholder en bildekopi
  986.                 //  av filteret som er valgt. Brukes kun av frihσndsfilteret.
  987.                 hdc = GetDC(HWindow);
  988.                 hdcMem = CreateCompatibleDC(hdc);
  989.                 hTempBitmap = CreateCompatibleBitmap(hdc, iW, iH);
  990.  
  991.                 if (hTempBitmap!=NULL)
  992.                 {
  993.                     //  Kopier dataene fra vinduets klientomrσde over i vσrt buffer.
  994.                     SelectObject(hdcMem, hTempBitmap);
  995.                     BitBlt(hdcMem, 0, 0, iW, iH, hdc, 0, 0,SRCCOPY);
  996.  
  997.                     //  Opprett det nye TComplexWindow objektet
  998.                     bShowFilter = FALSE;
  999.                     InvalidateRect(HWindow, NULL, FALSE);
  1000.                     ptNewComp=((TComplexWindow *)(((TMainWindow *)Parent)->CreateComplexChild(FileName, hNewComplex,
  1001.                                 bmpNewInfo, hNewBitmap)));
  1002.  
  1003.                     //  La det nye arve noen parametre fra det gamle
  1004.                     ptNewComp->iLowerValue=iLowerValue;
  1005.                     ptNewComp->iUpperValue=iUpperValue;
  1006.                     ptNewComp->iFilterType=iFilterType;
  1007.                     ptNewComp->bDirty=FALSE;
  1008.                     ptNewComp->MinLogAmplitude=MinLogAmplitude;
  1009.                     ptNewComp->MaxLogAmplitude=MaxLogAmplitude;
  1010.  
  1011.                     //  Vis det nye
  1012.                     UpdateWindow(ptNewComp->HWindow);
  1013.  
  1014.                     //  Be det nye filtrere seg selv
  1015.                     ptNewComp->ExecuteFilter(hdcMem);
  1016.                 }
  1017.                 else
  1018.                     MessageBox(HWindow, "Filter: Not enough memory to allocate scratchpicture",
  1019.                             ERROR_CAPTION, MB_ERROR);
  1020.                 ReleaseDC(HWindow, hdc);
  1021.                 DeleteDC(hdcMem);
  1022.                 DeleteObject(hTempBitmap);
  1023.             }
  1024.             else
  1025.                 MessageBox(HWindow, "Filter: Not enough memory to allocate new bitmap picture",
  1026.                         ERROR_CAPTION, MB_ERROR);
  1027.         }
  1028.         else
  1029.             MessageBox(HWindow, "TPictureWindow::FFT bmpNewInfo==NULL",
  1030.                     ERROR_CAPTION, MB_ERROR);
  1031.     }
  1032.     else
  1033.         MessageBox(HWindow, "Filter: Not enough memory to allocate new complex picture",
  1034.                 ERROR_CAPTION, MB_ERROR);
  1035. }
  1036.  
  1037. void TComplexWindow::ExecuteFilter(HDC hdcMem)
  1038. /****************************************************************************
  1039. Utf°rer selve filtreringen i det aktuelle objektet.
  1040.  
  1041. HDC hdcMem    En bildeflate som inneholder r°dfargen hvis det dreier
  1042.                         seg om frihσndsfilteret.
  1043.  
  1044. Kodet av:   MK    22.04.92
  1045. *****************************************************************************/
  1046. {
  1047.     int iX, iY, iMaxX, iMaxY, iW, iH;
  1048.     real rDistance, rH, rBWDistance, rTemp;
  1049.     real rMiddleX, rMiddleY, rT1, rT2;
  1050.     prcomplex huge *hpComp;
  1051.     BOOL bCancel, bRemove;
  1052.     char acTemp[50];
  1053.     HDC hdc;
  1054.     prcomplex comp;
  1055.  
  1056.     iW = (int)bmpInfo->bmiHeader.biWidth;
  1057.     iH = (int)bmpInfo->bmiHeader.biHeight;
  1058.     hdc = GetDC(HWindow);
  1059.     iMaxX = iW-1;
  1060.     iMaxY = iH-1;
  1061.     pdbProgress = new TProgressDialog(this, "PROGRESS", "Filter progress");
  1062.     GetApplication()->MakeWindow(pdbProgress);
  1063.     SendMessage(((TProgressDialog *)pdbProgress)->HWindow,
  1064.             WM_SETPROGRESSTEXT,
  1065.             0, (long)((LPSTR) "Filtering.."));
  1066.  
  1067.     //  Finn midtpunktet i bildet
  1068.     rMiddleX = ((real)iMaxX)/2;
  1069.     rMiddleY = ((real)iMaxY)/2;
  1070.     rBWDistance=(real)iLowerValue;
  1071.     for (iY=0;iY<=iMaxY;iY++)
  1072.     {
  1073.         SendMessage(pdbProgress->HWindow, WM_FIRST + WM_SETPROGRESS,
  1074.                 0, (((long)100*(iY))/(iMaxY)));
  1075.         if (bCancel=pdbProgress->CancelPressed())
  1076.             break;
  1077.         for (iX=0;iX<=iMaxX;iX++)
  1078.         {
  1079.             //  L°kkene over gσr gjennom alle punktene i bildet.
  1080.             //  bRemove forteller om det aktuelle punktet skal fjernes
  1081.             //  fra frekvensplanet.
  1082.             bRemove = FALSE;
  1083.  
  1084.             //  Hvis det dreier seg om noen av de filtreren som bruker
  1085.             //  radius som parametre (dvs. alle bortsett fra frihσnd)
  1086.             if (iFilterType!=CM_FILTERFREEHAND)
  1087.             {
  1088.                 //  Regn ut avstand fra et punkt i bildet til midten.
  1089.                 rT1 = (float)iX-rMiddleX;
  1090.                 rT2 = (float)iY-rMiddleY;
  1091.                 rDistance = (real)sqrt(rT1*rT1+rT2*rT2);
  1092.  
  1093.                 //  Ut i fra hva slags filtertype det dreier seg om, sjekk
  1094.                 //  avstanden og sett bRemove hvis denne skal fjernes.
  1095.                 switch (iFilterType)
  1096.                 {
  1097.                     case CM_FILTERLOWPASS:
  1098.                         if (rDistance>(real)iLowerValue)
  1099.                             bRemove=TRUE;
  1100.                         break;
  1101.                     case CM_FILTERHIGHPASS:
  1102.                         if (rDistance<(real)iLowerValue)
  1103.                             bRemove=TRUE;
  1104.                         break;
  1105.                     case CM_FILTERBANDSTOP:
  1106.                         if ((rDistance>(real)iLowerValue) && (rDistance<(real)iUpperValue))
  1107.                             bRemove=TRUE;
  1108.                         break;
  1109.                     case CM_FILTERBANDPASS:
  1110.                         if (!((rDistance>(real)iLowerValue) && (rDistance<(real)iUpperValue)))
  1111.                             bRemove=TRUE;
  1112.                         break;
  1113.                     case CM_FILTERBWLOWPASS:
  1114.                         //  Butterworth filtrene hσndteres spesiellt, her skal
  1115.                         //  alle punktene forandres ut i fra en formel.
  1116.                         GetComplex(hComplex, iX, iY, iW, iH, &comp);
  1117.                         if (rDistance!=0)
  1118.                         {
  1119.                             rTemp = rBWDistance/rDistance;
  1120.                             rH = 1/(1+rTemp*rTemp);
  1121.                         }
  1122.                         else
  1123.                             rH = 0;
  1124.                         comp.re *= rH;
  1125.                         comp.im *= rH;
  1126.                         SetComplex(hComplex, iX, iY, iW, iH, &comp);
  1127.                         break;
  1128.                     case CM_FILTERBWHIGHPASS:
  1129.                         //  Butterworth filtrene hσndteres spesiellt, her skal
  1130.                         //  alle punktene forandres ut i fra en formel.
  1131.                         GetComplex(hComplex, iX, iY, iW, iH, &comp);
  1132.                         if (rBWDistance!=0)
  1133.                         {
  1134.                             rTemp = rDistance/rBWDistance;
  1135.                             rH = 1/(1+rTemp*rTemp);
  1136.                         }
  1137.                         else
  1138.                             rH = 0;
  1139.                         comp.re *= rH;
  1140.                         comp.im *= rH;
  1141.                         SetComplex(hComplex, iX, iY, iW, iH, &comp);
  1142.                         break;
  1143.                 }
  1144.             }
  1145.             else
  1146.                 //  Hvis vi kommer hit dreier det seg om frihσndsfilteret
  1147.                 //  Vi leser fargen i bildet som representerer den r°dfargen
  1148.                 //  vi brukte og tegne med. Hvis disse matcher skal dette
  1149.                 //  punktet fjernes i det komplekse bildet.
  1150.                 if (GetPixel(hdcMem, iX, iY)==rgbRed)
  1151.                     bRemove = TRUE;
  1152.  
  1153.             //  Hvis et punkt skal vekk, fjern det i det komplekse,
  1154.             //  i bitmappen og pσ skjermen.
  1155.             if (bRemove)
  1156.             {
  1157.                 SetPixel(hdc, iX, iY, 0L);
  1158.                 SetComplex(hComplex, iX, iY, iW, iH, &compZero);
  1159.                 SetBMPPixel(hBitmap, iX, iY, iW, iH, 0);
  1160.             }
  1161.         }
  1162.     }
  1163.     ReleaseDC(HWindow, hdc);
  1164.     DestroyWindow(pdbProgress->HWindow);
  1165.  
  1166.     //  Hvis brukeren ikke har avbrutt filteroperasjonen..
  1167.     if (!bCancel)
  1168.     {
  1169.         //  Ikke vis filterellipsene
  1170.         bShowFilter = FALSE;
  1171.  
  1172.         //  Hvis det dreier seg om et butterworth filter mσ vi reskalere hele
  1173.         //  bildet siden alle punktene i bildet blir forandret.
  1174.         if ((iFilterType==CM_FILTERBWLOWPASS) || (iFilterType==CM_FILTERBWHIGHPASS))
  1175.         {
  1176.             bDirty = TRUE;
  1177.             bRescale = TRUE;
  1178.         }
  1179.         else
  1180.         //  Hvis ikke °nsker vi ikke σ reskalere bildet..
  1181.         {
  1182.             bRescale = FALSE;
  1183.             bDirty = FALSE;
  1184.         }
  1185.  
  1186.         //  Gi vinduet beskjed om σ oppdatere seg selv.
  1187.         InvalidateRect(HWindow, NULL, FALSE);
  1188.     }
  1189.     // Hvis brukeren har avbrutt filteroperasjonen, fjern dette
  1190.     // TComplexWindow objektet.
  1191.     else
  1192.         PostMessage(HWindow, WM_CLOSE, 0, 0);
  1193. }
  1194.  
  1195.  
  1196.